<!DOCTYPE html>
<title>Credential Manager: End-to-end tests for create() with a virtual authenticator.</title>
<script src="../resources/testharness.js"></script>
<script src="../resources/testharnessreport.js"></script>
<body>
<script type="module">
import {ACCEPTABLE_CREDENTIAL, ACCEPTABLE_CREDENTIAL_ID, authenticatorSetup, MAKE_CREDENTIAL_OPTIONS, deepCopy} from './resources/test-inputs.js';
import {TestAuthenticatorManager} from './resources/virtual-navigator-credentials.js';

const manager = new TestAuthenticatorManager;

if (document.location.host != "subdomain.example.test:8443") {
  document.location = "https://subdomain.example.test:8443/credentialmanager/credentialscontainer-create-with-virtual-authenticator.html";
  promise_test(_ => new Promise(_ => {}), "Stall tests on the wrong host.");
}

authenticatorSetup(manager, "CTAP2_0", () => {
  promise_test(async t => {
    let authenticators = await manager.authenticators();
    assert_equals(authenticators.length, 1);
    let testAuthenticator = authenticators[0];
    assert_true(await testAuthenticator.generateAndRegisterKey(ACCEPTABLE_CREDENTIAL_ID, "subdomain.example.test"));

    var customMakeCredOptions = deepCopy(MAKE_CREDENTIAL_OPTIONS);
    customMakeCredOptions.excludeCredentials = [ACCEPTABLE_CREDENTIAL];
    return promise_rejects_dom(t, "InvalidStateError",
      navigator.credentials.create({ publicKey : customMakeCredOptions}));
  }, "navigator.credentials.create() re-registration returns InvalidStateError");

  promise_test(async t => {
    var customMakeCredOptions = deepCopy(MAKE_CREDENTIAL_OPTIONS);
    customMakeCredOptions.rp.id = "";
    return promise_rejects_dom(t, "SecurityError",
      navigator.credentials.create({ publicKey : customMakeCredOptions}));
  }, "navigator.credentials.create() with empty rpId returns SecurityError");

  promise_test(async t => {
    var customMakeCredOptions = deepCopy(MAKE_CREDENTIAL_OPTIONS);
    customMakeCredOptions.authenticatorSelection.requireResidentKey = true;
    return navigator.credentials.create({ publicKey : customMakeCredOptions });
  }, "navigator.credentials.create() with requireResidentKey is supported");

  promise_test(async t => {
    var customMakeCredOptions = deepCopy(MAKE_CREDENTIAL_OPTIONS);
    customMakeCredOptions.authenticatorSelection.requireResidentKey = false;
    customMakeCredOptions.authenticatorSelection.residentKey = "required";
    return navigator.credentials.create({ publicKey : customMakeCredOptions });
  }, "navigator.credentials.create() resident_key overrides resident_key_required");

  promise_test(async t => {
    var customMakeCredOptions = deepCopy(MAKE_CREDENTIAL_OPTIONS);
    customMakeCredOptions.authenticatorSelection.residentKey = "required";
    return navigator.credentials.create({ publicKey : customMakeCredOptions });
  }, "navigator.credentials.create() with resident_key is supported");

  promise_test(async t => {
    var customMakeCredOptions = deepCopy(MAKE_CREDENTIAL_OPTIONS);
    customMakeCredOptions.authenticatorSelection.resident_key = "foobarbaz";
    return navigator.credentials.create({ publicKey : customMakeCredOptions });
  }, "navigator.credentials.create() invalid resident_key value is ignored");

  promise_test(async t => {
    const authAbortController = new AbortController();
    const authAbortSignal = authAbortController.signal;
    return navigator.credentials.create({ publicKey : MAKE_CREDENTIAL_OPTIONS, signal : authAbortSignal});
  }, "navigator.credentials.create() with abort signal flag not set");

  promise_test(async t => {
    const authAbortController = new AbortController();
    const authAbortSignal = authAbortController.signal;
    authAbortController.abort();
    const promise = navigator.credentials.create({ publicKey : MAKE_CREDENTIAL_OPTIONS, signal : authAbortSignal});
    return promise_rejects_dom(t, "AbortError", promise);
  }, "navigator.credentials.create() with abort signal flag set before sending request");

  promise_test(async t => {
    const authAbortController = new AbortController();
    const authAbortSignal = authAbortController.signal;
    const promise = navigator.credentials.create({ publicKey : MAKE_CREDENTIAL_OPTIONS, signal : authAbortSignal});
    authAbortController.abort();
    return promise_rejects_dom(t, "AbortError", promise);
  }, "navigator.credentials.create() with abort signal flag is set after sending request");

  promise_test(async t => {
    const authAbortController = new AbortController();
    const authAbortSignal = authAbortController.signal;
    const promise = await navigator.credentials.create({ publicKey : MAKE_CREDENTIAL_OPTIONS, signal : authAbortSignal});
    authAbortController.abort();
    return promise;
  }, "navigator.credentials.create() with abort signal flag is set after promise resolved");
}, {});

</script>
